#include "neighborhood2.h"
#include "freefuncs.h"

Neighborhood2::Neighborhood2()
{
	if (this->feature != NULL)
		delete[] this->feature;
	this->radius = NRADIUS;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	this->feature = new int[neighborhoodSize];
	for (int i = 0; i != neighborhoodSize; i++)
		this->feature[i] = 0;
	this->hash = 0;
}

Neighborhood2::Neighborhood2(int nRadius) : radius(nRadius)
{
	if (this->feature != NULL)
		delete[] this->feature;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	this->feature = new int[neighborhoodSize];
	for (int i = 0; i != neighborhoodSize; i++)
		this->feature[i] = 0;
	this->hash = 0;
}

Neighborhood2::Neighborhood2 (const Neighborhood2& other)
{
	if (this->feature != NULL)
		delete[] this->feature;
	this->radius = other.radius;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	this->feature = new int[neighborhoodSize];
	for (int i = 0; i != neighborhoodSize; i++)
		this->feature[i] = other.feature[i];
	this->hash = other.hash;
}

Neighborhood2::Neighborhood2 (const ImageMatrix& im, int row, int col, int radius): radius(radius)
{
	if (this->feature != NULL)
		delete[] this->feature;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	int index = 0;
	this->feature = new int[neighborhoodSize];
	for (int r = row - radius; r <= row + radius; r++ )
		for (int c = col - radius; c <= col + radius; c++)
			this->feature[index++] = im.getValue(r,c);
	this->updateHash();
}

Neighborhood2::Neighborhood2(string feature, int r): radius(r)
{
	if (this->feature != NULL)
		delete[] this->feature;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);	
	if (neighborhoodSize != (int) feature.size())
	{
		cerr << "Error: Invalid sized string was passed to create a Neighborhood2 object";
		//assert(false);
	}
	int a = 0;
	this->feature = new int[neighborhoodSize];
	for (int j = 0; j != neighborhoodSize; j++)
	{			
		setFeatureLeaveHash(j, feature.at(a++) - 48); //'0'=48, '1'=49, etc.
	}
	updateHash();
}

void Neighborhood2::updateHash()
{
	/************************************************************************/
	/* coefficients of features:
	/* 11111
	/* 22222
	/* 33333
	/* 44444
	/* 55555
	/************************************************************************/
	this->hash = 0;
	int index = 0;
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	int side = 2*radius + 1;
	for (int r = 1; r <= side; r++)
		for (int c = 1; c <= side; c++)
			this->hash += this->feature[index++] * r;
}

void Neighborhood2::updateFromHash(unsigned long hashValue)
{
	assert ("This function does not work in Neighborhood2. Not a one to one hashing.");
}

bool Neighborhood2::isEqual(const Neighborhood2& other) const
{
	//if (this->hash != other.hash)
	//	return false;
	//else
	{
		int neighborhoodSize = intPosPow((this->radius*2+1),2);
		for (int i = 0 ; i < neighborhoodSize; i++)
			if (feature[i] != other.feature[i])
				return false;
	}
	return true;
}

bool Neighborhood2::hasSameFeature(const Neighborhood2& other) const
{
	cout << "\nUse isEqual() instead. This returns false.\n";
		return false;
}

int Neighborhood2::getRadius() const
{
	return radius;
}

void Neighborhood2::setRadius(int r)
{
	radius = r;
}

void Neighborhood2::updateFromImageMatrix(const ImageMatrix& im, int row, int col, int radius)
{
	this->radius = radius;
	if (this->feature != NULL)
		delete[] feature; 
	int neighborhoodSize = intPosPow((this->radius*2+1),2);
	feature = new int[neighborhoodSize];
	int index = 0;

	for (int r = row - radius; r <= row + radius; r++ )
		for (int c = col - radius; c <= col + radius; c++)
			this->feature[index++] = im.getValue(r,c);
	this->updateHash();
}

int Neighborhood2::getSize() const
{
	return intPosPow((this->radius*2+1),2);
}

Neighborhood2::~Neighborhood2(void)
{
	if (feature != NULL)
		delete[] feature;
	feature = NULL;
	//delete[] feature;
}

std::ostream& operator<< (std::ostream& stream, const Neighborhood2& nb)
{
	int nbSize = nb.getSize();
	for (int i = 0; i < nbSize; ++i)
		stream << nb.feature[i] << ",";
	return stream;
}